import fs from "fs";
import got from "got";
import { load } from "cheerio";
import { HttpsProxyAgent } from "https-proxy-agent";
import {
  pipeline,
  makeDirs,
  getOrigin,
  countSize,
  state,
  history,
} from "./index.mjs";
import { proxy } from "../config.mjs";

const { address, useProxy } = proxy;
const headers = {
  "User-Agent":
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
  Referer: "",
  Cookie:
    "cf_clearance=QXXurGFVVgx9fE8Wv6_S9Wh_AfIjEr.3iKR4h6y4Rwk-1736503777-1.2.1.1-isIcdou3NCTsdA226hR3UwVjjaCnG8YNe3cIWQciF36hLdAZRsio2NqdhMMRg3bbNs7hYZ_IZohgIzXxsNoh7w9ukSMXczh1PXEtk8cO8bCElSk7F8hTrvqYnItsLnHIsSs.l_BpcuOC3j2w4d7Ehvjv1UU34_QzmHavm3x6Yl9NZ4AZbokCBfwynE1nAmn3_dBAio1I6O_Sis6QST1_mWxkPuSX_FZDtV3UjC1C9rkIO.K5JoqxCGxg.uO3RbNeGMNwHWvjdzsr_u3G_HC4.00soPgkG_EiNVNmMXlA9QGFcwFsS.Sq0jIdJDE74tO0e67iyhDiCm9lTm_1oLVy2Ll4F21vIiXB2qntzKo3w4_TR0CsVsLCythu7EAdPAfBKc22CoY7FOrKopTb072ub6p_sxpwD41IzG0qIKa4e6tkwpfcHCiBHNgv6bUTwatT;",
};
const agent = {
  https: new HttpsProxyAgent(address),
};

// 抓取页面
async function grabPage(url) {
  if (history.has(url)) return;
  history.set(url, 1);
  console.log("grabPage:", url);
  const response = await got(url, {
    headers, // 设置请求头
    ...(useProxy && {
      // 代理设置
      agent,
    }),
  }).catch((error) => {
    console.log("[抓取错误]:", error.message, url);
  });
  return load(response.body);
}
// 抓取页面中的图片
async function fetch(
  $,
  { selector = "img", pageName = "", directory = "./imgs/" } = {}
) {
  const imgElements = $(selector).toArray();
  await Promise.all(
    imgElements.map(async (element, index) => {
      let imgUrl = $(element).attr("data-src") || $(element).attr("src");
      if (!imgUrl.includes("http")) imgUrl = "https:" + imgUrl;
      // 下载图片
      return imgUrl && saveImg(imgUrl, directory, pageName + ++index);
    })
  );
}
// 保存图片
async function saveImg(url, directory, name) {
  let fileName = name + url.substring(url.lastIndexOf("."));
  if (fileName.includes("?"))
    fileName = fileName.substring(0, fileName.lastIndexOf("?"));
  const filePath = directory + fileName;
  // 图片已存在且大小不为 0
  if (fs.existsSync(filePath)) {
    const stats = fs.statSync(filePath);
    if (stats.size > 0) return console.log("图片已存在", fileName);
  }
  // 确保目录存在
  if (!fs.existsSync(directory)) makeDirs(directory);

  // 创建写入流
  const fileStream = fs.createWriteStream(filePath);
  // 监听写入结束事件
  fileStream.on("finish", () => {
    state.successNum++;
    console.log(`${fileName} 下载成功!`);
    countSize(filePath);
  });

  // 设置请求头
  headers.Referer = getOrigin(url);

  // 下载图片
  await download(url, fileStream).catch((error) => {
    state.retry.push({ url, filePath });
    console.log("[下载错误]:", fileName, error.message);
  });
}

// 结束逻辑
async function finish() {
  //处理下载失败待重试的图片
  console.log("\n待重试图片:", state.retry.length);
  while (state.retry.length) {
    const { url, filePath } = state.retry.pop();
    const fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
    const fileStream = fs.createWriteStream(filePath).on("finish", () => {
      state.successNum++;
      console.log(`${fileName} 下载成功! 剩余:${state.retry.length}`);
      countSize(filePath);
    });

    await download(url, fileStream, 10).catch((error) => {
      state.failPic.push({ url, filePath });
      console.log("[下载失败]:", fileName, error.message);
      fs.unlink(filePath, (err) => {
        if (err) console.log("[删除文件失败]");
      });
    });
  }
}
// 下载图片;
function download(url, fileStream, delay = 5) {
  return pipeline(
    got.stream(url, {
      headers,
      timeout: {
        connect: delay * 1000,
        socket: delay * 1000,
        request: delay * 1000,
      }, // 设置连接、套接字和请求超时时间
      retry: { limit: 1 }, // 设置重试次数
      ...(useProxy && {
        // 代理设置
        agent,
      }),
    }),
    fileStream
  );
}

export { fetch, grabPage, saveImg, finish };
